home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_c / cug233 / dskrpk.c < prev    next >
Text File  |  1987-06-30  |  22KB  |  614 lines

  1. /******************************************************************/
  2. /*     Directory repack                                           */
  3. /*     written by Rich Karas for the public domain                */
  4. /*     rev 1.0 1/23/86                                            */
  5. /*                                                                */
  6. /*                                                                */
  7. /*                                                                */
  8. /******************************************************************/
  9.  
  10. #include "stdio.h"
  11. #include "customiz.h"
  12. #define MAXSIZE 16383
  13. #define MINSIZE 8192
  14. #define MAXDIRS 512
  15. char fat[MINSIZE];
  16.      /*  these are global variables */
  17.  
  18. int drive,num_sect,begin,status,error,directory[MAXSIZE];
  19. unsigned int fat_strt,dir_strt,data_area,dir_len;
  20. unsigned int byte_sect,sect_unit,reserv_strt,no_fat,fat_sect,no_root;
  21. unsigned int sect_image,media,sect_track,no_heads,no_hidden;
  22. int *bufptr;
  23. #define UNDERL "\033\133\064\155\0"
  24. #define NORMAL "\033\133\155\0"
  25. #define REVERSE "\033\133\067\155\0"
  26. #define BOLD "\033\133\061\155\0"
  27. #define BLINK "\033\133\065\155\0"
  28. #define CLRSCR "\033\133\062\112\0"
  29. #define ERASELN "\033\133\113\0"
  30. #define XTIME 30
  31. #define CPOS1 "\033\133\065\073\062068\110\0"
  32. /******************************************************************/
  33. /*                                                                */
  34. /*    Introduction is a procedure that prints using ansii         */
  35. /*    ESCAPE codes to implement blinking and cusor position.      */
  36. /*                                                                */
  37. /*                                                                */
  38. /*                                                                */
  39. /******************************************************************/
  40.  
  41. intro()             /* introduces who we are */
  42. {
  43.  printf("%s",CLRSCR);
  44.  printf("%s",CPOS1);
  45.  printf("%s%s    DIRECTORY REPACK %s\n",BOLD,BLINK,NORMAL);
  46.  printf("\n\n\n\n\n\n");
  47.  printf("                      Rich Karas\n");
  48.  printf("                      14 Wells Road\n");
  49.  printf("                      Flemington,NJ 08822\n");
  50.  printf("                      Voice 201-782-0639\n");
  51.  printf("                      Data  201-782-7640\n");
  52.  printf("\n\n\n\n\n");
  53.  printf("            Public Domain Software 1986, Richard Karas \n");
  54.  printf("                        REV 1.0 1/23/86");
  55.  sleep(XTIME);
  56.  printf("%s",CLRSCR);
  57. }
  58. /******************************************************************/
  59. /*                                                                */
  60. /*     Select drive is an assembly language program which         */
  61. /*     calls DOS system functions to find out how many drives     */
  62. /*     are present.                                              */
  63. /*                                                                */
  64. /*                                                                */
  65. /******************************************************************/
  66.  
  67. select_drive()
  68. {
  69.   register int x;
  70. #asm
  71.      push ds
  72.      push ss
  73.      push ax
  74.      push dx
  75.      mov  ah,19h
  76.      int 21h
  77.      mov dl,al
  78.      mov ah,0eh
  79.      int 21h
  80.      mov di,ax
  81.      pop dx
  82.      pop ax
  83.      pop ss
  84.      pop ds
  85. #endasm
  86.     return( x & 0177);
  87. }
  88. /******************************************************************/
  89. /*                                                                */
  90. /*      Reset dsk does just what it says,using                    */
  91. /*      another DOS system call.                                  */
  92. /*                                                                */
  93. /*                                                                */
  94. /*                                                                */
  95. /******************************************************************/
  96.  
  97.  
  98. reset_dsk()
  99. {
  100. #asm
  101.      push ds
  102.      push ss
  103.      push ax
  104.      push dx
  105.      mov  ah,0dh
  106.      int 21h
  107.      pop dx
  108.      pop ax
  109.      pop ss
  110.      pop ds
  111. #endasm
  112. }
  113. /******************************************************************/
  114. /*                                                                */
  115. /*      Disk read performs absolute disk reads through            */
  116. /*      the system calls. IT reads X number of sectors begining   */
  117. /*       at sector specified.                                      */
  118. /*                                                                */
  119. /*                                                                */
  120. /******************************************************************/
  121.  
  122.  
  123. disk_read()  /* routine to perform absolute disk read */
  124. {
  125. #asm
  126.      push ds
  127.      push ax
  128.      push bx
  129.      push cx
  130.      push dx
  131.      mov  ax,DS:WORD PTR drive
  132.      mov  bx,offset bufptr
  133.      mov  dx,[bx]
  134.      mov  bx,dx
  135.      mov  cx,DS:WORD PTR num_sect
  136.      mov  dx,DS:WORD PTR begin
  137.      int  25h
  138.      pushf
  139.      mov  DS:WORD PTR error,ax
  140.      pop  ax
  141.      mov  DS:WORD PTR status,ax
  142.      popf
  143.      pop  dx
  144.      pop  cx
  145.      pop  bx
  146.      pop  ax
  147.      pop  ds
  148. #endasm
  149. }
  150. /******************************************************************/
  151. /*                                                                */
  152. /*            Same as read, but writes to disk.                   */
  153. /*                                                                */
  154. /*                                                                */
  155. /*                                                                */
  156. /*                                                                */
  157. /******************************************************************/
  158.  
  159. disk_write()  /* routine to perform absolute disk write */
  160. {
  161. #asm
  162.      push ds
  163.      push ax
  164.      push bx
  165.      push cx
  166.      push dx
  167.      mov  ax,DS:WORD PTR drive
  168.      mov  bx,offset bufptr
  169.      mov  dx,[bx]
  170.      mov  bx,dx
  171.      mov  cx,DS:WORD PTR num_sect
  172.      mov  dx,DS:WORD PTR begin
  173.      int  26h
  174.      pushf
  175.      mov  DS:WORD PTR error,ax
  176.      pop  ax
  177.      mov  DS:WORD PTR status,ax
  178.      popf
  179.      pop  dx
  180.      pop  cx
  181.      pop  bx
  182.      pop  ax
  183.      pop  ds
  184. #endasm
  185. }
  186. /******************************************************************/
  187. /*                                                                */
  188. /*        Operator enters the disk dirve to repack.               */
  189. /*                                                                */
  190. /*                                                                */
  191. /*                                                                */
  192. /*                                                                */
  193. /******************************************************************/
  194.  
  195. prompt(k)  /* prompts for operator entry of drive to dir repack */
  196. int k;
  197. {
  198.   char j,num;
  199.   int i;
  200.   j=65;
  201.   drive=0;
  202.   printf("Please select disk drive to repack directories \n");
  203.   printf("          ");
  204.   for(i=0;i<k;i++)
  205.      {  printf("  %c",j);
  206.         j=j+1;
  207.         }
  208.   printf("\n Drive = ");
  209.   scanf("%c",&num);      /* gets operator value and converts to upper */
  210.   num=toupper(num);
  211.   printf("\n\n");
  212.   i=num-65;
  213.   if(i>k) {
  214.       printf(" drive selected is not configured in system");
  215.       exit(0);
  216.       }
  217.   else
  218.      drive=i;
  219. }
  220. /******************************************************************/
  221. /*         This procedure analysis the media discription and      */
  222. /*         performs some math. It also and displays these         */
  223. /*         attributes.                                            */
  224. /*         It reads the boot sector byte offset 11-29.            */
  225. /*                                                                */
  226. /*                                                                */
  227. /******************************************************************/
  228.  
  229.  
  230. attrib()
  231. {
  232.   double val1[1],val2[1],val3[1],val4[1],val5[1];
  233.   char l1[100];
  234.   int temp,i;
  235.   fat_sect=directory[11];      /* ref dos manual for explanation */
  236.   sect_track=directory[12];
  237.   no_heads=directory[13];
  238.   no_hidden=directory[14];
  239.   reserv_strt=directory[7];
  240.   media=(directory[10] & 0xff00)>>8;
  241.   no_fat=directory[8] & 0x00ff;
  242.   sect_unit=(directory[6] & 0xff00)>>8;
  243.   temp=(directory[6] & 0x00ff)<<8;
  244.   byte_sect=temp;
  245.   temp=(directory[9] & 0x00ff)<<8;
  246.   no_root=temp + ((directory[8] & 0xff00)>>8);
  247.   temp=(directory[10] & 0x00ff)<<8;
  248.   sect_image=temp + ((directory[9] & 0xff00) >>8);
  249.   int2bcd(val1,sect_image);
  250.   int2bcd(val4,byte_sect);
  251.   bmul(val5,val4,val1);
  252.   format(l1,val5);
  253.  
  254.  
  255.      /* do some math to find attributes */
  256.   fat_strt=reserv_strt;
  257.   dir_strt=fat_strt+(fat_sect*no_fat);
  258.   if (no_root >= 1024) {
  259.      dir_len=no_root/byte_sect;
  260.      dir_len=dir_len*32;
  261.   } else {
  262.      dir_len=((no_root*32)/byte_sect);
  263.   }
  264.   data_area=dir_strt+dir_len;
  265.      /* display media attributes */
  266.   printf("%s",CLRSCR);
  267.   printf("\n  Media description and capacity");
  268.   printf("\n\n");
  269.   printf("Boot area starts at sector   0\n");
  270.   printf("FAT tables begin at sector %d\n",fat_strt);
  271.   printf("Directory begins at sector %d\n",dir_strt);
  272.   printf("Data area begins at sector %d\n",data_area);
  273.   printf("Total sectors on the disk is %d\n",sect_image);
  274.   printf("Number of sectors per track is %d\n",sect_track);
  275.   printf("Number of heads used to read/write is %d\n",no_heads);
  276.   printf("Media byte descriptor is %x\n",media);
  277.   printf("Sectors per allocation unit is %d\n",sect_unit);
  278.   puts("Total bytes of storage are ");
  279.   puts(l1);
  280. }
  281. /******************************************************************/
  282. /*                                                                */
  283. /*      Determines if absolute disk read/writes were valid,       */
  284. /*        aborts if found in error.                               */
  285. /*                                                                */
  286. /*                                                                */
  287. /*                                                                */
  288. /******************************************************************/
  289.  
  290. valid()  /* check status for bit 0=1 or 0 than print error if 1 */
  291. {
  292.  
  293.    status=status & 1;
  294.    if(status==1) {
  295.       printf("\n Error detected during disk read/write \n");
  296.       switch (error) {
  297.          case 0:
  298.               printf("\n\n Attempt to write to protected disk");
  299.               exit(1);
  300.          case 1:
  301.               printf("\n\n Unknown unit ");
  302.               exit(1);
  303.          case 2:
  304.               printf("\n\n Drive not ready ");
  305.               exit(1);
  306.          default :
  307.               printf("\n\n Error type %d check DOS manual \n\n",error);
  308.               exit(1);
  309.               }
  310.        }
  311. }
  312. /******************************************************************/
  313. /*                                                                */
  314. /*    This routine repacks the root directory only.               */
  315. /*         It calls the proceedure subrepack if it                */
  316. /*         finds a subdirectory. Since the root directory is      */
  317. /*        a fixed number of entries, I coded this as standalone.  */
  318. /*                                                                */
  319. /******************************************************************/
  320.  
  321. repack()
  322. {
  323.     int firstbyte,attribute,i,n,j,true,more;
  324.     char name[12];
  325.     unsigned int cln,count;
  326.     more=0;
  327.     count=1;
  328.     true=1;
  329.     n=0;
  330.     printf("\n\nAanlyzing & packing ROOT directory \n");
  331.     firstbyte=directory[n]&0x00ff;
  332.     attribute=(directory[n+5]&0xff00)>>8;
  333.     while(true) {
  334.        if(attribute ==0x0010 && firstbyte != 0x00e5) {
  335.             disk_write();                        /* found a subdir */
  336.             for(i=0,j=0;i<=8;i=i+2,j++) {
  337.                name[i]=directory[n+j]&0x00ff;
  338.                name[i+1]=(directory[n+j]&0xff00)>>8;
  339.                }
  340.             name[10]=directory[n+5]&0x00ff;
  341.             name[11]='\0';
  342.             i=directory[n+13]&0x00ff <<8;
  343.             j=directory[n+13]&0xff00 >>8;
  344.             cln=i+j;
  345.             n=n+16;
  346.             firstbyte=directory[n]&0x00ff;
  347.             attribute=(directory[n+5]&0xff00)>>8;
  348.             subrepack(&name,cln,5);
  349.             bufptr=&directory;
  350.             num_sect=dir_len;
  351.             begin=dir_strt;
  352.             disk_read();
  353.             valid();
  354.        }else{
  355.             if(firstbyte==0x00e5) {
  356.               more=look(no_root,count,n);
  357.               if(more==1){            /* move up if more valid entries */
  358.                 moveup(n,no_root,count);
  359.                 firstbyte=directory[n]&0x00ff;
  360.                 attribute=(directory[n+5]&0xff00)>>8;
  361.               }else
  362.                 true=0;
  363.             }else {
  364.                  n=n+16;      /* keep looking for deletes until done */
  365.                  firstbyte=directory[n]&0x00ff;
  366.                  attribute=(directory[n+5]&0xff00)>>8;
  367.                }
  368.        }
  369.        count=count+1;
  370.        if(firstbyte ==0 || count > no_root)
  371.           true=0;
  372.     }
  373.     disk_write();
  374.     valid();
  375.     printf("Root directory repack complete\n\n");
  376. }
  377. /******************************************************************/
  378. /*                                                                */
  379. /*     This is a recursive routine which I've tested to a depth   */
  380. /*     of five subdiredctories. Basically it performes the same   */
  381. /*     as the root directory repack routine with the exception    */
  382. /*     of unlimites number of directory entries.                  */
  383. /*                                                                */
  384. /******************************************************************/
  385.  
  386. subrepack(name,cluster,tab)
  387. char name[];
  388. int tab;
  389. unsigned int cluster;
  390. {
  391.     int firstbyte,attribute,i,j,n,l,true,more;
  392.     unsigned int ctr,logical[32],next,offset,newclu,count,no_of_dir;
  393.     double val1[1],val2[1],val3[1],val4[1];
  394.     char newname[12];
  395.     more=0;
  396.     n=0;
  397.     true=1;
  398.     for(i=1;i<tab;i++)
  399.        printf(" ");
  400.     printf("Working on subdirectory %s\n",name);
  401.     for(i=0;i<32;i++)
  402.        logical[i]=0;
  403.     i=0;
  404. cont: logical[i]=((cluster-2)*sect_unit)+data_area;
  405.     s2bcd(val2,"1.5");             /* this is where we convert cluster */
  406.     int2bcd(val1,cluster);        /* to logical sector number and */
  407.     bmul(val3,val1,val2);         /* figure out the offset into the FAT */
  408.     s2bcd(val4,".4");
  409.     bsub(val1,val3,val4);
  410.     offset=bcd2int(val1);
  411.     if(cluster % 2 ==0)  {
  412.        next=(fat[offset+1] & 0x0f) <<8;
  413.        next=next +fat[offset];
  414.     } else {
  415.            next=(fat[offset] &0xf0) >>4;
  416.            next=next + (fat[offset+1] << 4);
  417.            }
  418.     cluster=next;
  419.     i=i+1;
  420.     if(cluster < 0xff7)
  421.       goto cont;    /* now can read new subdir and proces */
  422.       num_sect=sect_unit;
  423.       ctr=i;
  424.       n=0;
  425.       no_of_dir=(16*sect_unit)*(ctr);
  426.       count=1;
  427.       for(j=0;j<ctr;j++) {       /* get the subdirectory data */
  428.          begin=logical[j];
  429.          bufptr=&directory[n];
  430.          disk_read();
  431.          valid();
  432.          n=n+((sect_unit*byte_sect)/2);
  433.          if(n > MAXSIZE) {
  434.              printf("\n\n To many files for anyone to control !! ");
  435.              exit(1);
  436.              }
  437.        }
  438.        n=32;           /* same as root directory routine */
  439.        firstbyte=directory[n]&0x00ff;
  440.        attribute=(directory[n+5]&0xff00)>>8;
  441.        while(true) {
  442.             if(attribute == 0x0010 && firstbyte != 0x00e5 ) {
  443.                 for(j=0,i=0;j<ctr;j++) {
  444.                    begin=logical[j];
  445.                    bufptr=&directory[i];
  446.                    disk_write();
  447.                    valid();
  448.                    i=i+((sect_unit*byte_sect)/2);
  449.                    }
  450.                 for(i=0,j=0;i<=8;i=i+2,j++) {
  451.                    newname[i]=directory[n+j]&0x00ff;
  452.                    newname[i+1]=(directory[n+j]&0xff00)>>8;
  453.                    }
  454.                 newname[10]=directory[n+5]&0x00ff;
  455.                 newname[11]='\0';
  456.                 i=directory[n+13]&0x00ff<<8;
  457.                 j=directory[n+13]&0xff00>>8;
  458.                 newclu=i+j;
  459.                 n=n+16;
  460.                 firstbyte=directory[n]&0x00ff;
  461.                 attribute=(directory[n+5]&0xff00)>>8;
  462.                 subrepack(&newname,newclu,tab+5);
  463.                 for(j=0,i=0;j<ctr;j++) {
  464.                    begin=logical[j];
  465.                    bufptr=&directory[i];
  466.                    disk_read();
  467.                    valid();
  468.                    i=i+((sect_unit*byte_sect)/2);
  469.                    }
  470.             } else {
  471.                    if(firstbyte==0x00e5) {
  472.                        more=look(no_of_dir,count,n);
  473.                        if(more==1){
  474.                           moveup(n,no_of_dir,count);
  475.                           firstbyte=directory[n]&0x00ff;
  476.                           attribute=(directory[n+5]&0xff00)>>8;
  477.                           }else
  478.                              true=0;
  479.                        } else {
  480.                               n=n+16;
  481.                               firstbyte=directory[n]&0x00ff;
  482.                               attribute=(directory[n+5]&0xff00)>>8;
  483.                               }
  484.                     }
  485.                     count=count+1;
  486.                     if(firstbyte ==0 || count > no_of_dir)
  487.                        true=0;
  488.        }
  489.        for(j=0,i=0;j<ctr;j++) {
  490.            begin=logical[j];
  491.            bufptr=&directory[i];
  492.            disk_write();
  493.            valid();
  494.            i=i+((sect_unit*byte_sect)/2);
  495.            }
  496.        for(i=0;i<tab;i++)
  497.           printf(" ");
  498.        printf("Repacking complete on %s\n",name);
  499. }
  500. /******************************************************************/
  501. /*                                                                */
  502. /*      Routine that deletes unused directory entries             */
  503. /*      located in the middle of valid entries, By moving         */
  504. /*      valid entries up.                                         */
  505. /*                                                                */
  506. /*                                                                */
  507. /******************************************************************/
  508.  
  509.  
  510. moveup(start,no_of_dir,prescnt)
  511. int start;
  512. unsigned int no_of_dir,prescnt;
  513. {
  514.     int i,true;
  515.     true=1;         /* get rid of deleted by moving valid entries up */
  516.     do{
  517.        for(i=0;i<=15;i++)
  518.            directory[start+i]=directory[start+i+16];
  519.        start=start+16;
  520.        prescnt=prescnt+1;
  521.        if((directory[start]&0x00ff) == 0 || prescnt > no_of_dir)
  522.          true=0;
  523.     }while(true);
  524. }
  525.  
  526. /******************************************************************/
  527. /*                                                                */
  528. /*       Routine to look ahead  and determine if additional       */
  529. /*            valid directory entries exist                       */
  530. /*                                                                */
  531. /*                                                                */
  532. /*                                                                */
  533. /******************************************************************/
  534.  
  535. int look(maxentries,start,ent1)
  536. unsigned int maxentries,ent1;
  537. int start;
  538. {
  539.   unsigned int i,q;
  540.   q=0;
  541.   for(i=start;i<=maxentries;i++) {
  542.    if((directory[ent1]&0x00ff)== 0x00e5 ||(directory[ent1]&0x00ff)==0x0000)
  543.     ;
  544.    else                 /* if no more valid entries at end of dir */
  545.         q=1;            /* than don't do anymore (lookahead) */
  546.    ent1=ent1+16;
  547.    }
  548.    return(q);
  549. }
  550. /******************************************************************/
  551. /*     Main code which calls the above proceedures                */
  552. /*        This also analyzes the input parameters to              */
  553. /*            determine if operator prompt is required.           */
  554. /*                It will also analyze the media data and         */
  555. /*                    abort the program if it is invalid.         */
  556. /*                                                                */
  557. /******************************************************************/
  558.  
  559.  
  560. main(argc,argv)
  561. int argc;
  562. char *argv[];
  563. {
  564.     int num,point;
  565.     char media1;
  566.     intro();
  567.     reset_dsk();              /* introduce the writer */
  568.     num=select_drive();   /* how many drives in system */
  569.     num_sect=1;
  570.     begin=0;
  571.     bufptr=&directory;    /* read sector 0 to get device attributes */
  572.     drive=0;
  573.     if(argc ==1)      /* did the operator pass parameters */
  574.        prompt(num);
  575.     else {
  576.          point=argv[1] [0];     /* if yess don't prompt */
  577.          point=toupper(point);
  578.          point=point-65;
  579.          if(point>=0 && point <=num)
  580.             drive=point;
  581.          else {
  582.               printf("Usage : Dskrpk [drive],or drive not there");
  583.               exit(1);
  584.               }
  585.          }
  586.     disk_read();
  587.     valid();
  588.     attrib();
  589.                /* display info about drive selected */
  590.     if(no_root > 1024) {
  591.         printf("\nThis program supports IBM floppy,10mb,20mb drives only");
  592.         exit(1);
  593.         }
  594.     bufptr=&fat;
  595.     num_sect=fat_sect;
  596.     begin=fat_strt;
  597.     disk_read();           /* get fat information */
  598.     valid();
  599.     media1=fat[0];
  600.     if(media != media1) {
  601.       printf(" \n\n Boot sector and FAT sector media disagree");
  602.       printf(" \n     I cannot repack this drive ");
  603.       exit(1);
  604.       }
  605.     bufptr=&directory;
  606.     begin=dir_strt;
  607.     num_sect=dir_len;
  608.     disk_read();       /* get root directory information */
  609.     valid();
  610.     repack();        /* call to repack directories */
  611.     exit(0);
  612. }
  613.  
  614.